// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_RENDERER_MEDIA_ANDROID_MEDIA_INFO_LOADER_H_
#define CONTENT_RENDERER_MEDIA_ANDROID_MEDIA_INFO_LOADER_H_

#include <stdint.h>

#include <memory>
#include <string>

#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "media/blink/active_loader.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/web/WebAssociatedURLLoaderClient.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "url/gurl.h"

namespace blink {
class WebAssociatedURLLoader;
class WebFrame;
class WebURLRequest;
}

namespace content {

// This class provides additional information about a media URL. Currently it
// can be used to determine if a media URL has a single security origin and
// whether the URL passes a CORS access check.
class CONTENT_EXPORT MediaInfoLoader
    : private blink::WebAssociatedURLLoaderClient {
public:
    // Status codes for start operations on MediaInfoLoader.
    enum Status {
        // The operation failed, which may have been due to:
        //   - Page navigation
        //   - Server replied 4xx/5xx
        //   - The response was invalid
        //   - Connection was terminated
        //
        // At this point you should delete the loader.
        kFailed,

        // Everything went as planned.
        kOk,
    };

    // Callback when MediaInfoLoader finishes loading the url. Args: whether URL
    // is successfully loaded, the final URL destination following all the
    // redirect, the first party URL for the final destination, and whether
    // credentials needs to be sent to the final destination.
    typedef base::Callback<void(Status, const GURL&, const GURL&, bool)> ReadyCB;

    // Start loading information about the given media URL.
    // |url| - URL for the media resource to be loaded.
    // |cors_mode| - HTML media element's crossorigin attribute.
    // |ready_cb| - Called when media info has finished or failed loading.
    MediaInfoLoader(
        const GURL& url,
        blink::WebMediaPlayer::CORSMode cors_mode,
        const ReadyCB& ready_cb);
    ~MediaInfoLoader() override;

    // Start loading media info.
    void Start(blink::WebFrame* frame);

    // Returns true if the media resource has a single origin, false otherwise.
    // Only valid to call after the loader becomes ready.
    bool HasSingleOrigin() const;

    // Returns true if the media resource passed a CORS access control check.
    // Only valid to call after the loader becomes ready.
    bool DidPassCORSAccessCheck() const;

private:
    friend class MediaInfoLoaderTest;

    // blink::WebAssociatedURLLoaderClient implementation.
    bool willFollowRedirect(
        const blink::WebURLRequest& newRequest,
        const blink::WebURLResponse& redirectResponse) override;
    void didSendData(unsigned long long bytesSent,
        unsigned long long totalBytesToBeSent) override;
    void didReceiveResponse(const blink::WebURLResponse& response) override;
    void didDownloadData(int data_length) override;
    void didReceiveData(const char* data, int data_length) override;
    void didReceiveCachedMetadata(const char* data, int dataLength) override;
    void didFinishLoading(double finishTime) override;
    void didFail(const blink::WebURLError&) override;

    void DidBecomeReady(Status status);

    // Injected WebAssociatedURLLoader instance for testing purposes.
    std::unique_ptr<blink::WebAssociatedURLLoader> test_loader_;

    // Keeps track of an active WebAssociatedURLLoader and associated state.
    std::unique_ptr<media::ActiveLoader> active_loader_;

    bool loader_failed_;
    GURL url_;
    GURL first_party_url_;
    bool allow_stored_credentials_;
    blink::WebMediaPlayer::CORSMode cors_mode_;
    bool single_origin_;

    ReadyCB ready_cb_;
    base::TimeTicks start_time_;

    DISALLOW_COPY_AND_ASSIGN(MediaInfoLoader);
};

} // namespace content

#endif // CONTENT_RENDERER_MEDIA_ANDROID_MEDIA_INFO_LOADER_H_
